package com.aube.multiscreen;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.ViewGroup;

import com.aube.R;
import com.aube.guide.GuideConstants;
import com.aube.model.ImageItem;
import com.aube.model.TimeLinePiece;
import com.aube.model.VideoItem;
import com.huyn.baseframework.model.ChannelDetail;
import com.huyn.baseframework.statistics.AubeStatisticEvents;
import com.huyn.baseframework.statistics.AubeStatisticTool;
import com.huyn.baseframework.statistics.EventValuePair;
import com.huyn.baseframework.utils.Constant;
import com.huyn.baseframework.utils.StringUtils;
import com.huyn.baseframework.utils.Utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by huyaonan on 15/11/14.
 */
public class MultiCameraTransitionHelper implements IVideoController {

    private List<ImageItem> animPics = new ArrayList<>();
    private List<ImageItem> targetPics = new ArrayList<>();

    private List<ImageItem> exePics = new ArrayList<>();

    private ImageItem mMiddleSizePic;
    private ImageItem mFullSizePic;

    private ImageItem mStandardSideItem;
    private ImageItem mStandardHideItem;

    private ImageItem mPicInMiddleSize, mPicInFullSize;

    private HashMap<Integer, ImageItem> mImgMaps = new HashMap<>();

    private int size = 5;

    public static int GAP = 40;

    public static final int DURATION = 300;

    private AtomicBoolean mAnimRunning = new AtomicBoolean(false);

    private int currentIndex = 0;
    private volatile boolean fullScreen = true;

    public IVideoStateListener mListener;

    protected MultiCameraView picView;

    private int fixedSizeWSmall = 0;
    private int fixedSizeHSmall = 0;
    private int width = 0;
    private int height = 0;

    private AtomicBoolean mRemoved = new AtomicBoolean(false);

    private AtomicBoolean mEnableSoundSwitcher = new AtomicBoolean(false);

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if(msg.what == RESET_ANIM_STATE)
                mAnimRunning.set(false);
        }
    };
    private static final int RESET_ANIM_STATE = 33333;

    public MultiCameraTransitionHelper() {}

    public void bindView(MultiCameraView view) {
        this.picView = view;
    }

    public void start() {
        if (picView != null)
            picView.start();
    }

    public void pause() {
        if (picView != null)
            picView.pause();
    }

    public void pauseWhenFreeze() {
        if(picView != null)
            picView.pauseWhenFreeze();
    }

    public void updateProgress(long current) {
        if (picView != null)
            picView.updateProgress(current);
    }

    public int getGap() {
        return GAP;
    }

    public long getCurrentProgress() {
        if(mListener != null)
            return mListener.getCurrentProgress();
        return 0;
    }

    public long getDuration() {
        if(mListener != null)
            return mListener.getDuration();
        return 0;
    }

    /**
     * 获取右侧多镜头排列的起始纵坐标
     * @param size 右侧分镜头数量
     * @return
     */
    private int getSideStartY(int size) {
        if(fixedSizeWSmall == 0 || fixedSizeHSmall == 0) {
            width = picView.getWidth();
            height = picView.getHeight();

            fixedSizeWSmall = (int) (width * 0.247);
            fixedSizeHSmall = (int) (width * 0.247 * 9 / 16);

            GAP = (int) ((1 - 0.66f - 0.247f) * width / 3);
        }

        int totalHeight = fixedSizeHSmall * size + GAP * (size+1);

        return totalHeight > height ? GAP : ((height - totalHeight) / 2 + GAP);
    }

    public int getRightSideHeight(int size) {
        int startY = getSideStartY(size);
        return startY + size * (fixedSizeHSmall + GAP);
    }

    private void initArgs(boolean forceUpdate) {
        int x = 0, y = 0;
        int startY = getSideStartY(size-1);

        if(mStandardSideItem == null) {
            x = width - fixedSizeWSmall - GAP;
            mStandardSideItem = new ImageItem(fixedSizeWSmall, fixedSizeHSmall, x, startY);
            mStandardHideItem = new ImageItem(fixedSizeWSmall, fixedSizeHSmall, width, startY);
        }

        if(forceUpdate) {
            exePics = new ArrayList<>();
        }

        if (exePics.size() == 0) {
            for (int i = 0; i < size; i++) {
                exePics.add(new ImageItem());
            }
        }

        if (mMiddleSizePic == null) {
            int mWidth = (int) (width * 0.66f);
            int mHeight = (int) (width * 0.66 * 9 / 16);

            mMiddleSizePic = new ImageItem(mWidth, mHeight, GAP, (height - mHeight) / 2);
        }

        if (mFullSizePic == null) {
            mFullSizePic = new ImageItem(width, height, 0, 0);
        }

        if (mPicInMiddleSize == null) {
            int wSmall = (int) (0.199 * width);
            int hSmall = (int) (0.199 * width * 9 / 16);
            mPicInMiddleSize = new ImageItem(wSmall, hSmall, mMiddleSizePic.x + mMiddleSizePic.width - GAP - wSmall, mMiddleSizePic.y + mMiddleSizePic.height - GAP - hSmall);
        }

        if (mPicInFullSize == null) {
            int wSmall = (int) (0.296 * width);
            int hSmall = (int) (0.296 * width * 9 / 16);
            mPicInFullSize = new ImageItem(wSmall, hSmall, width - GAP - wSmall, height - GAP - hSmall);
        }
    }

    /**
     * 生成初始多镜头的位置和大小数组
     * @return
     */
    private List<ImageItem> generateVideoSizeArray() {
        List<ImageItem> result = new ArrayList<>();
        for (int i=0; i<size; i++) {
            if (i == 0) {
                result.add(mFullSizePic);

                mImgMaps.put(i, mFullSizePic);
            } else {
                int y = mStandardSideItem.y + (i-1) * (GAP + fixedSizeHSmall);
                ImageItem item = new ImageItem(mStandardSideItem.width, mStandardSideItem.height, width, y);//从右边入场
                result.add(item);

                mImgMaps.put(i, item);
            }
        }
        return result;
    }

    public void addViews(TimeLinePiece data, boolean play) {
        List<VideoItem> videos = data.getVideos();
        Utils.Log(TAG, ">>>>>>>>>>start to add video,size:" + videos.size());
        this.size = videos.size() + 1;
        initArgs(true);
        mEnableSoundSwitcher.set(initVideoNew(generateVideoSizeArray(), videos, data.startSeconds, play));
    }

    public void doSeek(long current) {
        if(picView != null && picView.getChildCount() > 1) {
            picView.doSeek(current);
        }
    }

    private boolean initVideoNew(List<ImageItem> beginPics, List<VideoItem> videos, long startTime, boolean play) {
        int maxHeight = getRightSideHeight(videos.size());
        picView.setSize(maxHeight);
        return picView.initVideos(beginPics, videos, startTime, play, this);
    }

    @Override
    public int getCurrentIndex() {
        return currentIndex;
    }

    @Override
    public void switchView(View v) {
        if (mListener != null)
            mListener.changeState(false);
        //reinit anim list
        try {
            int index = (int) v.getTag(R.id.card_index);
            if (currentIndex != -1) {
                if (currentIndex != index) {
                    if (picView.isInPic(index)) {
                        //画中画切换
                        exchangePIP(index, ((CameraCardView) v).getTitle());
                    } else {
                        GuideConstants.switchGuidePerformed(picView.getContext());
                        //交换
                        exchangeSideAndMain(index);
                    }

                    String id = ((CameraCardView) picView.findViewWithTag(index + "")).getVideoId();
                    AubeStatisticTool.getInstance(picView.getContext()).report(AubeStatisticEvents.MULTIVIDEO_CLICK,
                            AubeStatisticEvents.formatValues(new EventValuePair("vid", getChannelDetail().videoid), new EventValuePair("target", id)));

                    if(mListener != null)
                        mListener.mainVideoChanged(index);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public long getStartTime() {
        return 0;
    }

    /**
     * 在全屏模式才有效
     */
    @Override
    public void showTools() {
//        if(fullScreen) {
        if (mListener != null)
            mListener.manageTools();
//        }
    }

    public void showTools(int time) {
        if(mListener != null)
            mListener.showTools(time);
    }

    /**
     * 从画中画中拖出视频
     * @param mRoot
     * @param mId
     * @param currentX
     * @param currentY
     * @param mListener
     */
    public void dragFromMainPic(final View mRoot, String mId, float currentX, float currentY, final IAnimEndListener mListener) {
        if(isAnimRunning())
            return;
        toggleAnimState(true);

        printEndRoute("拉出画中画=====START");

        List<String> views = picView.getRightSideViews();

        ImageItem start = new ImageItem(mRoot.getWidth(), mRoot.getHeight(), currentX, currentY);
        mImgMaps.put(Integer.parseInt(mId), start);

        List<String> ids = new ArrayList<>();
        boolean hasExist = false;
        for(String id : views) {
            ids.add(id);
            if(mId.equalsIgnoreCase(id))
                hasExist = true;
        }
        if(!hasExist)
            ids.add(mId);

        List<ImageItem> mOris = new ArrayList<>();
        List<ImageItem> mEnd = new ArrayList<>();

        Iterator<Map.Entry<String, ImageItem>> iter = sortSideVideos(ids);
        int standY = getSideStartY(ids.size());
        int index = 0;

        List<String> targetIds = new ArrayList<>();

        while (iter.hasNext()) {
            Map.Entry<String, ImageItem> entry = iter.next();

            int id = Integer.parseInt(entry.getKey());
            mOris.add(getCopyById(id));

            ImageItem item;
            if(fullScreen)
                item = new ImageItem(fixedSizeWSmall, fixedSizeHSmall, mStandardHideItem.x, standY + (fixedSizeHSmall+GAP)*index);
            else
                item = new ImageItem(fixedSizeWSmall, fixedSizeHSmall, mStandardSideItem.x, standY + (fixedSizeHSmall+GAP)*index);

            mEnd.add(item);
            Utils.Log(TAG, "new size:w:" + item.width + "_h:" + item.height + "_x:" + item.x + "_y:" + item.y);
            mImgMaps.put(id, item.copy());

            targetIds.add(entry.getKey());

            index++;
        }

        picView.removeFromPicInPicSet(mId);
        picView.addToSideSet(mId);

        printEndRoute("拉出画中画=====END");

        ObjectAnimator anim = ObjectAnimator.ofObject(this, "resizeAll", new AutoFitEvaluator(), new ImageList(mOris, targetIds), new ImageList(mEnd, targetIds));
        anim.setDuration(DURATION);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                ((CameraCardView) mRoot).hideTitle(false);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                toggleAnimState(false);

                if (mListener != null)
                    mListener.animEnd();
            }
        });
        anim.start();
    }

    /**
     * 点击 x 的时候画中画消失
     * @param mRoot
     * @param id
     */
    @Override
    public void removeFromMainPic(final CameraCardView mRoot, final String id) {
        if(isAnimRunning())
            return;
        toggleAnimState(true);

        //将当前画中画移除
        animPics.clear();
        targetPics.clear();

        printEndRoute("点X多镜头归位_____start, remove:" + id);

        List<String> views = picView.getRightSideViews();
        Iterator<Map.Entry<String, ImageItem>> iter = sortSideVideos(views);
        int standY = getSideStartY(views.size() + 1);
        int index = 0;
        HashMap<Integer, ImageItem> mTemp = new HashMap<>();
        while (iter != null && iter.hasNext()) {
            Map.Entry<String, ImageItem> entry = iter.next();

            int mId = Integer.parseInt(entry.getKey());
            if(fullScreen) {
                ImageItem item = new ImageItem(fixedSizeWSmall, fixedSizeHSmall, mStandardHideItem.x, standY + (fixedSizeHSmall + GAP) * index);
                mTemp.put(mId, item);
            } else {
                ImageItem item = new ImageItem(fixedSizeWSmall, fixedSizeHSmall, mStandardSideItem.x, standY + (fixedSizeHSmall + GAP) * index);
                mTemp.put(mId, item);
            }
            index++;
        }
        if(fullScreen)
            mTemp.put(Integer.parseInt(id), new ImageItem(fixedSizeWSmall, fixedSizeHSmall, mStandardHideItem.x, standY + (fixedSizeHSmall+GAP)*index));
        else
            mTemp.put(Integer.parseInt(id), new ImageItem(fixedSizeWSmall, fixedSizeHSmall, mStandardSideItem.x, standY + (fixedSizeHSmall+GAP)*index));

        int count = picView.getChildCount();

        for (int i = 0; i < count; i++) {
            int tag = Integer.parseInt((String) picView.getChildAt(i).getTag());
            animPics.add(getCopyById(tag));

            if(!mTemp.containsKey(tag)) {
                targetPics.add(getCopyById(tag));
            } else {
                targetPics.add(mTemp.get(tag));
                mImgMaps.put(tag, mTemp.get(tag).copy());
            }
        }

        picView.removeFromPicInPicSet(id);
        picView.addToSideSet(id);

        /**将缩放按钮展示出来 Jan 12 2017*/
        if (mListener != null && fullScreen)
            mListener.toFullScreen(mRoot.getTitle(), mRoot.isVr());

        ObjectAnimator anim = ObjectAnimator.ofObject(this, "reLoc", new PointEvaluator(), new ImageItem(), new ImageItem());
        anim.setDuration(DURATION);

        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                mRoot.hideTitle(false);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                toggleAnimState(false);

                mRoot.manageAudioAndMask(true);
                if(fullScreen)
                    mRoot.manageSound(false);
            }
        });

        printEndRoute("点X多镜头归位");
        anim.start();
    }

    @Override
    public boolean enableSoundSwitch() {
        return isSoundSwitchEnabled();
    }

    /**
     * 好像暂时没有用
     * @param current
     */
    @Override
    public void exchangeSound(int current) {
        if(picView == null)
            return;

        for(int i=1; i<picView.getChildCount(); i++) {
            if(i == current)
                continue;
            CameraCardView child = (CameraCardView) picView.findViewWithTag(""+i);
            if(child.isSoundOn())
                child.soundOff();
        }
    }

    @Override
    public boolean isMiddleMode() {
        return !fullScreen;
    }

    @Override
    public ChannelDetail getChannelDetail() {
        return mListener != null ? mListener.getChannelDetail() : null;
    }

    @Override
    public void suspendAllPlayers() {
        if(picView != null)
            picView.suspendAllPlayers();
    }

    @Override
    public void notifyAllPlayers() {
        if(picView != null)
            picView.notifyAllPlayers();
    }

    @Override
    public void endPlay(int id) {
//        HashMap<String, String> ids = new HashMap<>();
//        ids.put(id+"", id+"");
//        removeAndRelayoutViews(ids);
    }

    @Override
    public void exchangeViewSize(String title, boolean toBig, boolean isVr) {
        if (mListener != null)
            mListener.toFullScreen(title, isVr);
        exchangeMode(toBig);
    }

    @Override
    public void initToolBar(boolean onMajorVideo) {
        if(mListener != null)
            mListener.initToolBar(onMajorVideo);
    }

    @Override
    public boolean isPlaying() {
        if(mListener != null)
            return mListener.isPlaying();
        return false;
    }

    @Override
    public void updateProgressBySubVideo(long current) {
        if(mListener != null)
            mListener.updateProgressBySubVideo(current);
    }

    /**
     * 画中画切换
     * @param index
     */
    private void exchangePIP(final int index, String title) {
        if(isAnimRunning())
            return;
        toggleAnimState(true);

        animPics.clear();
        targetPics.clear();

        printEndRoute("画中画切换_____start");

        int focusIndex = 0;
        int targetIndex = 0;

        int focusI = 0;
        int targetI = 0;
        int count = picView.getChildCount();
        for (int i = 0; i < count; i++) {
            int tag = Integer.parseInt((String) picView.getChildAt(i).getTag());

            animPics.add(getImageItem(tag));
            targetPics.add(getImageItem(tag));

            if (tag == currentIndex) {
                focusIndex = tag;
                focusI = i;
            } else if (tag == index) {
                targetIndex = tag;
                targetI = i;
            }
        }

        if(mListener != null)
            mListener.updateTitle(title);

        ImageItem tempPicTarget = getCopyById(targetIndex);
        ImageItem tempPicFocus = getCopyById(focusIndex);

        targetPics.remove(focusI);
        targetPics.add(focusI, tempPicTarget);
        targetPics.remove(targetI);
        targetPics.add(targetI, tempPicFocus);

        mImgMaps.put(focusIndex, tempPicTarget.copy());
        mImgMaps.put(targetIndex, tempPicFocus.copy());

        ObjectAnimator anim = ObjectAnimator.ofObject(this, "reLoc", new PointEvaluator(), new ImageItem(), new ImageItem());
        anim.setDuration(DURATION);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                picView.hideAll(index, currentIndex);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                picView.removeFromPicInPicSet(index + "");
                picView.addToPicInPicSet(currentIndex + "");

                //change view
                picView.swapDisplayState(index, currentIndex, true);
                picView.relaodViewStack(index, true);

                currentIndex = index;

                toggleAnimState(false);
            }
        });

        printEndRoute("画中画切换");

        anim.start();
    }

    /**
     * 多镜头开始快进快退
     */
    public void onStartTrackingTouch() {
        if (mListener != null)
            mListener.onStartTrackingTouch();
    }

    /**
     * 快进/快退
     */
    public void manageProgress(boolean forward, float ratio, boolean doSeek) {
        if (mListener != null)
            mListener.manageProgress(forward, ratio, doSeek);
    }

    /**
     * 取消快进快退
     */
    public void cancelSeek() {
        if(mListener != null)
            mListener.cancelSeek();
    }

    /**
     * 重置进度条的信息
     */
    public void endUpdateProgress() {
        if(mListener != null)
            mListener.endUpdateProgress();
    }

    /**
     * 从全屏模式退回来
     */
    public boolean reverseFromFullScreen(boolean exitMultiVideo) {
        if (!fullScreen)
            return false;

        if(picView.getRightSidePicSize() == 0)
            return false;

        ((CameraCardView) picView.findViewWithTag(currentIndex + "")).switchWindowSize(false);

        //显示画中画的des
        picView.showDes();

        exchangeMode(false);

        if (mListener != null)
            mListener.reserveFullScreen(exitMultiVideo);

        return true;
    }

    private void swap(int arg1, int arg2) {
        ImageItem ii1 = getCopyById(arg1);
        ImageItem ii2 = getCopyById(arg2);
        mImgMaps.put(arg1, ii2);
        mImgMaps.put(arg2, ii1);
    }

    public void updateImageItemByIndex(String index, ImageItem item) {
        mImgMaps.put(Integer.parseInt(index), item.copy());
    }

    public void updateImageItemByIndex(String index, float transitionY) {
        ImageItem item = getImageItem(Integer.parseInt(index));
        if(item == null)
            return;
        item.updateY(transitionY);
    }

    /**
     * 画面显示位置和大小交换
     * @param index
     */
    private void exchangeSideAndMain(final int index) {
        if(isAnimRunning())
            return;
        toggleAnimState(true);

        initArgs(false);
        animPics.clear();
        targetPics.clear();

        printEndRoute("主画面和分镜头切换_____start");

        int childeCount = picView.getChildCount();
        for (int i = 0; i < childeCount; i++) {
            int id = Integer.parseInt((String) picView.getChildAt(i).getTag());
            animPics.add(getCopyById(id));
            if (id == index)
                targetPics.add(getCopyById(currentIndex));
            else if (id == currentIndex)
                targetPics.add(getCopyById(index));
            else
                targetPics.add(getCopyById(id));
        }

        swap(currentIndex, index);

        ObjectAnimator anim = ObjectAnimator.ofObject(this, "reLoc", new PointEvaluator(), new ImageItem(), new ImageItem());
        anim.setDuration(DURATION);

        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                picView.hideAll(index, currentIndex);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                picView.swap(index, currentIndex);
                picView.relaodViewStack(index, false);
                currentIndex = index;

                toggleAnimState(false);
            }
        });

        printEndRoute("主画面和分镜头切换");

        anim.start();
    }

    public ImageItem getImageItem(int index) {
        if(mImgMaps.containsKey(index))
            return mImgMaps.get(index);
        Utils.Log(Utils.LogType.ERROR, TAG, "getImageItem:" + index + " in mImgMaps is null");
        return mStandardHideItem.copy();
    }

    /**
     * 全屏/多镜头模式切换
     *
     * @param toBig
     */
    public void exchangeMode(final boolean toBig) {
        if(isAnimRunning())
            return;
        toggleAnimState(true);

        animPics.clear();
        targetPics.clear();
        printEndRoute((toBig ? "全屏模式" : "主镜头-分镜头模式") + "_____start");

        if (mListener != null)
            mListener.switchGoodsHotpotSize(toBig);

        int count = picView.getChildCount();

        //重新排列画中画
        int picInPicSize = picView.getPicInPicSize();
        if (toBig) {
            HashMap<Integer, ImageItem> mTemp = new HashMap<>();
            for (int i = 0; i < picInPicSize; i++) {
                String mId = picView.getPicId(i);
                ImageItem item = getImageItem(Integer.parseInt(mId));
                //按比例拉伸边距
                int mRight = mMiddleSizePic.x + mMiddleSizePic.width - item.x - item.width;
                int mBottom = mMiddleSizePic.y + mMiddleSizePic.height - item.y - item.height;
                int mLeft = item.x - mMiddleSizePic.x;
                int mTop = item.y - mMiddleSizePic.y;

                ImageItem target = new ImageItem();
                target.width = mPicInFullSize.width;
                target.height = mPicInFullSize.height;
                if(mLeft >= mRight)
                    target.x = (int) (mFullSizePic.width - mPicInFullSize.width - (mFullSizePic.width * mRight * 1f/mMiddleSizePic.width));
                else
                    target.x = (int) (mFullSizePic.width * mLeft *1f/ mMiddleSizePic.width);
                if(mTop >= mBottom)
                    target.y = (int) (mFullSizePic.height - mPicInFullSize.height - (mFullSizePic.height * mBottom * 1f/mMiddleSizePic.height));
                else
                    target.y = (int) (mFullSizePic.height * mTop *1f/ mMiddleSizePic.height);
                mTemp.put(Integer.parseInt(mId), target.copy());
            }

            //ImageItem standardSize = oriPics.get(oriPics.size() - 1);
            //int hideX = hidePics.get(hidePics.size() - 1).x;
            int hideX = mStandardHideItem.x;

            for (int i = 0; i < count; i++) {
                int tag = Integer.parseInt((String) picView.getChildAt(i).getTag());
                animPics.add(getCopyById(tag));

                if (currentIndex == tag) {
                    targetPics.add(mFullSizePic);

                    mImgMaps.put(tag, mFullSizePic);
                } else {
                    if (picView.isInPic(tag)) {
                        targetPics.add(mTemp.get(tag).copy());

                        mImgMaps.put(tag, mTemp.get(tag).copy());
                    } else if(picView.isChildVisible(tag)) {
                        //ImageItem item = new ImageItem(standardSize.width, standardSize.height, hideX, getImageItem(tag).y);
                        ImageItem item = new ImageItem(mStandardSideItem.width, mStandardSideItem.height, hideX, getImageItem(tag).y);
                        targetPics.add(item);

                        mImgMaps.put(tag, item.copy());
                    } else {
                        targetPics.add(getCopyById(tag));
                    }
                }
            }

            fullScreen = true;
        } else {
            HashMap<Integer, ImageItem> mTemp = new HashMap<>();
            for (int i = 0; i < picInPicSize; i++) {
                String mId = picView.getPicId(i);
                ImageItem item = getImageItem(Integer.parseInt(mId));

                //按比例拉升边距
                int mRight = mFullSizePic.width - item.x - item.width;
                int mBottom = mFullSizePic.height - item.y - item.height;
                int mLeft = item.x;
                int mTop = item.y;
                ImageItem target = new ImageItem();
                target.width = mPicInMiddleSize.width;
                target.height = mPicInMiddleSize.height;
                if(mLeft >= mRight)
                    target.x = (int) (mMiddleSizePic.width + mMiddleSizePic.x - mPicInMiddleSize.width - (mMiddleSizePic.width * mRight * 1f/mFullSizePic.width));
                else
                    target.x = (int) (mMiddleSizePic.x + mMiddleSizePic.width * mLeft *1f/ mFullSizePic.width);
                if(mTop >= mBottom)
                    target.y = (int) (mMiddleSizePic.height + mMiddleSizePic.y - mPicInMiddleSize.height - (mMiddleSizePic.height * mBottom * 1f/mFullSizePic.height));
                else
                    target.y = (int) (mMiddleSizePic.y + mMiddleSizePic.height * mTop *1f/ mFullSizePic.height);
                mTemp.put(Integer.parseInt(mId), target.copy());
            }

            //ImageItem standardSize = oriPics.get(oriPics.size() - 1);
            //int hideX = oriPics.get(oriPics.size() - 1).x;
            int hideX = mStandardSideItem.x;

            for (int i = 0; i < count; i++) {
                int tag = Integer.parseInt((String) picView.getChildAt(i).getTag());
                animPics.add(getCopyById(tag));

                if (currentIndex == tag) {
                    targetPics.add(mMiddleSizePic);

                    mImgMaps.put(tag, mMiddleSizePic);
                } else {
                    if (picView.isInPic(tag)) {
                        targetPics.add(mTemp.get(tag).copy());
                        mImgMaps.put(tag, mTemp.get(tag).copy());
                    } else if(picView.isChildVisible(tag)) {
                        //ImageItem item = new ImageItem(standardSize.width, standardSize.height, hideX, getImageItem(tag).y);
                        ImageItem item = new ImageItem(mStandardSideItem.width, mStandardSideItem.height, hideX, getImageItem(tag).y);
                        targetPics.add(item);

                        mImgMaps.put(tag, item);
                    } else {
                        targetPics.add(getCopyById(tag));
                    }
                }
            }

            fullScreen = false;
        }

        printEndRoute(toBig ? "全屏模式" : "主镜头-分镜头模式");

        ObjectAnimator anim = ObjectAnimator.ofObject(this, "reLoc", new PointEvaluator(), new ImageItem(), new ImageItem());
        anim.setDuration(DURATION);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                toggleAnimState(false);

                picView.silentSideVideo(toBig);
            }
        });
        anim.start();
    }

    /**
     * 在已有多镜头的基础上, 新增或者移除一到多个镜头
     * @param data
     * @param current
     */
    public void manageVideos(TimeLinePiece data, final long current) {
        if(isAnimRunning())
            return;

        HashMap<String, VideoItem> videos = data.getVideosMapByTime(current);
        if(videos == null || videos.size() == 0)
            return;

        final HashMap<String, Boolean> mVideoState = picView.manageVideos(videos);
        //Utils.Log(TAG, "++++++++++++++++++++++++++++++++++++" + current + "/" + mVideoState.size());
        if(mVideoState == null || mVideoState.size() == 0)
            return;

        toggleAnimState(true);

        boolean replaceMain = replaceMain(data.getDefaultId(), videos);
        String targetId = data.getDefaultId();
        HashMap<String, String> indexIdMap = picView.generateVideoMap(videos);

        animPics.clear();
        targetPics.clear();
        printEndRoute("重新排列多镜头_____start");

        if (mListener != null)
            mListener.switchGoodsHotpotSize(false);

        boolean sideSetChanged = false;
        final int lastIndex=currentIndex;
        boolean targetPip = false;
        boolean lastState = fullScreen;

        HashMap<Integer, ImageItem> mTemp = new HashMap<>();
        Iterator<String> iterator = mVideoState.keySet().iterator();
        while(iterator.hasNext()) {
            String id = iterator.next();
            String videoId = indexIdMap.get(id+"");

            Utils.Log(TAG, "iterator new videos : " + id + "/vid:" + videoId + "---" + replaceMain + "/target:" + targetId);

            //新加入的镜头
            if(mVideoState.get(id)) {
                picView.setChildVisible(id, current);
                //替换主镜头
                if(replaceMain && targetId.equalsIgnoreCase(videoId)) {
                    if(videos.get(videoId).isPipMode()) {
                        picView.addToPicInPicSet(currentIndex + "");

                        mTemp.put(currentIndex, getImageItemByCoordinate(videos.get(videoId)));
                        targetPip = true;
                    } else {
                        picView.addToSideSet(currentIndex + "");
                        sideSetChanged = true;
                    }
                    picView.removeFromSideSet(id+"");

                    currentIndex = Integer.parseInt(id);

                    mImgMaps.put(Integer.parseInt(id), new ImageItem(width, height, -width, 0));
                } else {
                    if(videos.get(videoId).isPipMode()) {
                        picView.removeFromSideSet(id+"");
                        picView.addToPicInPicSet(id+"");

                        mTemp.put(Integer.parseInt(id), getImageItemByCoordinate(videos.get(videoId)));
                        targetPip = true;
                    } else {
                        sideSetChanged = true;
                    }
                }
            } else {
                //需要消失的视频
                if (id.equalsIgnoreCase(currentIndex + "")) {
                    //主镜头进行切换
                    if (picView.isInPic(0)) {
                        picView.removeFromPicInPicSet("0");
                    } else {
                        picView.removeFromSideSet("0");
                        sideSetChanged = true;
                    }

                    currentIndex = 0;
                    //物品热点跟随主视频
                    if(mListener != null)
                        mListener.mainVideoChanged(0);
                    picView.swapDisplayState(0, Integer.parseInt(id), false);

                    //向左飞出
                    ImageItem item = getImageItem(Integer.parseInt(id));
                    mTemp.put(Integer.parseInt(id), new ImageItem(item.width, item.height, -item.width, item.y));
                } else {
                    if (picView.isInPic(id)) {
                        picView.removeFromPicInPicSet(id);
                    } else {
                        picView.removeFromSideSet(id);
                        sideSetChanged = true;
                    }

                    //向右飞出
                    ImageItem item = getImageItem(Integer.parseInt(id));
                    mTemp.put(Integer.parseInt(id), new ImageItem(item.width, item.height, mFullSizePic.width, item.y));
                }
            }
        }

        Utils.Log(TAG, "check is sideSetIsChanged:" + sideSetChanged);

        if(lastState && targetPip && !sideSetChanged) {
            fullScreen = lastState;
        } else {
            fullScreen = picView.getRightSidePicSize() == 0;
        }

        if(sideSetChanged) {
            List<String> views = picView.getRightSideViews();
            Iterator<Map.Entry<String, ImageItem>> iter = sortSideVideos(views);
            int standY = getSideStartY(views.size());
            int index = 0;
            while (iter != null && iter.hasNext()) {
                Map.Entry<String, ImageItem> entry = iter.next();

                int mId = Integer.parseInt(entry.getKey());
                ImageItem item = new ImageItem(fixedSizeWSmall, fixedSizeHSmall, mStandardSideItem.x, standY + (fixedSizeHSmall + GAP) * index);
                mTemp.put(mId, item);
                index++;
            }
        }

        if(!fullScreen) {
            int PIPCount = picView.getPicInPicSize();
            for (int i = 0; i < PIPCount; i++) {
                String mId = picView.getPicId(i);
                ImageItem item = getImageItem(Integer.parseInt(mId));

                //按比例拉升边距
                int mRight = mFullSizePic.width - item.x - item.width;
                int mBottom = mFullSizePic.height - item.y - item.height;
                int mLeft = item.x;
                int mTop = item.y;
                ImageItem target = new ImageItem();
                target.width = mPicInMiddleSize.width;
                target.height = mPicInMiddleSize.height;
                if (mLeft >= mRight)
                    target.x = (int) (mMiddleSizePic.width + mMiddleSizePic.x - mPicInMiddleSize.width - (mMiddleSizePic.width * mRight * 1f / mFullSizePic.width));
                else
                    target.x = (int) (mMiddleSizePic.x + mMiddleSizePic.width * mLeft * 1f / mFullSizePic.width);
                if (mTop >= mBottom)
                    target.y = (int) (mMiddleSizePic.height + mMiddleSizePic.y - mPicInMiddleSize.height - (mMiddleSizePic.height * mBottom * 1f / mFullSizePic.height));
                else
                    target.y = (int) (mMiddleSizePic.y + mMiddleSizePic.height * mTop * 1f / mFullSizePic.height);
                mTemp.put(Integer.parseInt(mId), target.copy());
            }
        }

//        HashMap<String, CameraCardView> mVideos = picView.getVisibleChildren();
        int count = picView.getChildCount();
        for (int i = 0; i < count; i++) {
            String id = (String) picView.getChildAt(i).getTag();

            //如果view不可见,继续下一个
//            if(!mVideos.containsKey(id))
//                continue;

            int tag = Integer.parseInt(id);
            animPics.add(getCopyById(tag));

            if(tag == currentIndex) {
                if(fullScreen) {
                    targetPics.add(new ImageItem(width, height, 0, 0));
                    mImgMaps.put(tag, new ImageItem(width, height, 0, 0));
                } else {
                    targetPics.add(mMiddleSizePic.copy());
                    mImgMaps.put(tag, mMiddleSizePic.copy());
                }
            } else {
                if(mTemp.containsKey(tag)) {
                    targetPics.add(mTemp.get(tag).copy());
                    mImgMaps.put(tag, mTemp.get(tag).copy());
                } else {
                    //不变
                    targetPics.add(getCopyById(tag));
                }
            }
        }

        if(replaceMain) {
            if(currentIndex != lastIndex) {
                //物品热点跟随主视频
                if (mListener != null)
                    mListener.mainVideoChanged(currentIndex);
                picView.swapDisplayState(currentIndex, lastIndex, targetPip);

                if (mListener != null)
                    mListener.updateTitle(((CameraCardView) picView.findViewWithTag(currentIndex + "")).getTitle());
            }
        }

        printEndRoute("重新排列多镜头");

        ObjectAnimator anim = ObjectAnimator.ofObject(this, "reLoc", new PointEvaluator(), new ImageItem(), new ImageItem());
        anim.setDuration(DURATION);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                if(fullScreen)
                    ((CameraCardView) picView.findViewWithTag(currentIndex+"")).hideAll();
                else
                    ((CameraCardView) picView.findViewWithTag(currentIndex+"")).showTitle();

                //改变主界面的工具条样式
                initToolBar(fullScreen);
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                toggleAnimState(false);

                Iterator<String> iterator = mVideoState.keySet().iterator();
                while(iterator.hasNext()) {
                    String id = iterator.next();
                    if(!mVideoState.get(id))
                        picView.removeView(id);
                }

                try {
                    if(!fullScreen)
                        ((CameraCardView) picView.findViewWithTag(currentIndex + "")).switchWindowSize(false);
                    //显示画中画的des
                    picView.showDes();

                    Utils.Log("VOICE", "...................manageVideos");
                    ((CameraCardView) picView.findViewWithTag(currentIndex+"")).managePadding(!fullScreen, false);

                    //bring all to front
                    if(currentIndex != lastIndex) {
                        Utils.Log(TAG, "move all view to front except " + currentIndex);
                        picView.bringLeftToFront(currentIndex);
                    }

                    //中屏幕模式展现
                    if(!fullScreen)
                        picView.showSwitchGuide();
                } catch (Exception e) {
                    e.printStackTrace();
                }

                if(mListener != null)
                    mListener.reserveFullScreen(false);

            }
        });
        anim.start();
    }

    /**
     * 卡片进场动画
     */
    public void cardIn(TimeLinePiece data, final long current, final IEnterAndExitListener listener) {
        Utils.Log(TAG, "cardinanim:::start execute cardin anim");
        if(isAnimRunning())
            return;
        toggleAnimState(true);
        final HashMap<String, VideoItem> videos = data.getVideosMapByTime(current);

        Utils.Log(TAG, "cardinanim:::check video size");
        if(videos == null || videos.size() == 0)
            return;

        Utils.Log(TAG, "cardinanim:::video size is positive");
//        if(!picView.hasChanged(videos))
//            return;
        if (mListener != null)
            mListener.switchGoodsHotpotSize(false);

        picView.setChildVisible(videos, current);

        initArgs(false);
        animPics.clear();
        targetPics.clear();

        printEndRoute("++++++++++++++++++++++++++++++execute cardin anim start");

        final int targetIndex = initCardAnimArgs(data.getDefaultId(), videos);

        ObjectAnimator anim = ObjectAnimator.ofObject(this, "reLoc", new PointEvaluator(), new ImageItem(), new ImageItem());
        anim.setDuration(DURATION);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                currentIndex = targetIndex;
                if(fullScreen)
                    ((CameraCardView) picView.findViewWithTag(targetIndex+"")).hideAll();
                else
                    ((CameraCardView) picView.findViewWithTag(targetIndex+"")).showTitle();
                //mMainScreen.show();

                //改变主界面的工具条样式
                initToolBar(fullScreen);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                toggleAnimState(false);

                //mMainScreen.managePadding(true, false);
                Utils.Log("VOICE", "...................cardIn");
                ((CameraCardView) picView.findViewWithTag(targetIndex+"")).managePadding(!fullScreen, false);

                //bring all to front
                if(targetIndex != 0) {
                    Utils.Log(TAG, "move all view to front except " + targetIndex);
                    picView.bringLeftToFront(targetIndex);
                }

//                if(!fullScreen) {
                    //显示画中画的des
                    picView.showDes();
//                }

                //中屏幕模式展现
                if(!fullScreen)
                    picView.showSwitchGuide();

                if(listener != null)
                    listener.onEnter();
            }
        });
        anim.start();

        printEndRoute("++++++++++++++++++++++++++++++execute cardin anim end");
    }

    private ImageItem getImageItemByCoordinate(VideoItem item) {
        ImageItem result = new ImageItem();
        result.width = mPicInFullSize.width;
        result.height = mPicInFullSize.height;
        int x = (int) (width * item.getX());
        int y = (int) (height * item.getY());
        result.x = x < 0 ? 0 : (x > width-mPicInFullSize.width ? width-mPicInFullSize.width : x);
        result.y = y < 0 ? 0 : (y > height-mPicInFullSize.height ? height-mPicInFullSize.height : y);
        return result;
    }

    private ImageItem getImageItemByCoordinateInPip(VideoItem item) {
        ImageItem result = new ImageItem();
        result.width = mPicInFullSize.width;
        result.height = mPicInFullSize.height;
        result.x = width;
        int y = (int) (height * item.getY());
        result.y = y < 0 ? 0 : (y > height-mPicInFullSize.height ? height-mPicInFullSize.height : y);
        return result;
    }

    private boolean replaceMain(String id, HashMap<String, VideoItem> videos) {
        if(StringUtils.isNotBlank(id) && videos != null && videos.containsKey(id))
            return true;
        return false;
    }

    /**
     * 多镜头入场动画初始和结束位置设置
     * @param vId
     * @param videos
     */
    private int initCardAnimArgs(String vId, HashMap<String, VideoItem> videos) {
        boolean replaceMain = replaceMain(vId, videos);
        boolean targetPip = false;
        int pipIndex=-1;
        fullScreen = true;

        HashMap<Integer, ImageItem> mStartMaps = new HashMap<>();
        HashMap<Integer, ImageItem> mTargetMaps = new HashMap<>();
        Iterator<Map.Entry<String, VideoItem>> iter = picView.generateVideoIterator(videos);
        List<String> sideVideoIdList = new ArrayList<>();
        Utils.Log(TAG, "initCardAnimArgs:targetVID is " + vId);
        while (iter != null && iter.hasNext()) {
            Map.Entry<String, VideoItem> item = iter.next();
            int mId = Integer.parseInt(item.getKey());
            VideoItem videoItem = item.getValue();

            Utils.Log(TAG, "iterator:" + mId + "___" + videoItem.getVideoId());

            if(replaceMain && vId.equalsIgnoreCase(videoItem.getVideoId())) {
                mStartMaps.put(0, getCopyById(0));
                mStartMaps.put(mId, new ImageItem(width, height, -width, 0));
                if (videoItem.isPipMode()) {
                    //和主镜头交换属性
                    mTargetMaps.put(0, getImageItemByCoordinate(videoItem));
                    mTargetMaps.put(mId, new ImageItem(width, height, 0, 0));
                    targetPip = true;
                    Utils.Log(TAG, "initCardAnimArgs:exchange with main video");
                    picView.addToPicInPicSet("0");
                } else {
                    sideVideoIdList.add("0");
                    mTargetMaps.put(mId, mMiddleSizePic.copy());
                    fullScreen = false;
                    picView.addToSideSet("0");
                }
                picView.removeFromSideSet(mId+"");
            } else {
                if (videoItem.isPipMode()) {
                    mTargetMaps.put(mId, getImageItemByCoordinate(videoItem));
                    mStartMaps.put(mId, getImageItemByCoordinateInPip(videoItem));
                    targetPip = true;

                    picView.removeFromSideSet(mId+"");
                    picView.addToPicInPicSet(mId+"");
                } else {
                    sideVideoIdList.add(item.getKey());
                    fullScreen = false;
                }
            }
        }

        Utils.Log(TAG, "reset start position : " + sideVideoIdList.size());
        int standY = getSideStartY(sideVideoIdList.size());
        int index = 0;
        for(String id : sideVideoIdList) {
            int mId = Integer.parseInt(id);

            int y = standY + (fixedSizeHSmall + GAP) * index;
            ImageItem endItem = new ImageItem(fixedSizeWSmall, fixedSizeHSmall, mStandardSideItem.x, y);

            ImageItem startItem = new ImageItem(fixedSizeWSmall, fixedSizeHSmall, mStandardHideItem.x, y);
            if(mId == 0) {
                mTargetMaps.put(0, endItem.copy());
                //mStartMaps.put(mId, startItem.copy());
            } else {
                String vedioId = picView.getVideoIdByIndex(id);
                Utils.Log(TAG, "set sidevideo position : " + vedioId + "/" + id + "/index:" + index);
                VideoItem videoItem = videos.get(vedioId);
                if(videoItem == null)
                    continue;

                if (replaceMain && vId.equalsIgnoreCase(id)) {
                    //have done
                } else {
                    mStartMaps.put(mId, startItem.copy());
                    if (videoItem.isPipMode()) {
                        //have done
                    } else {
                        mTargetMaps.put(mId, endItem.copy());
                    }
                }
            }
            index++;
        }

        if(!replaceMain && !targetPip) {
            mTargetMaps.put(0, mMiddleSizePic.copy());
            mStartMaps.put(0, getCopyById(0));
        }

        /**log*/
        if(Constant.DEBUG) {
            Iterator<Map.Entry<Integer, ImageItem>> startIter = mStartMaps.entrySet().iterator();
            while (startIter.hasNext()) {
                Map.Entry<Integer, ImageItem> entry = startIter.next();
                ImageItem item = entry.getValue();
                Utils.Log(TAG, "id:" + entry.getKey() + ":/" + item.width + '/' + item.height + "/" + item.x + "/" + item.y);
            }
            Utils.Log(TAG, "+++++++++++++++++++++++++++++++++");
            Iterator<Map.Entry<Integer, ImageItem>> endIter = mTargetMaps.entrySet().iterator();
            while (endIter.hasNext()) {
                Map.Entry<Integer, ImageItem> entry = endIter.next();
                ImageItem item = entry.getValue();
                Utils.Log(TAG, "id:" + entry.getKey() + ":/" + item.width + '/' + item.height + "/" + item.x + "/" + item.y);
            }
        }

        Utils.Log(TAG, "+++++++++++++++++++++++++++++++++");
        int count = picView.getChildCount();
        int targetIndex = 0;
        for(int i=0; i<count; i++) {
            CameraCardView view = (CameraCardView) picView.getChildAt(i);
            String videoId = view.getVideoId();
            String id = (String) view.getTag();
            int tag = Integer.parseInt(id);

            Utils.Log(TAG, "fullfill anim args:" + tag + "/vid:" + videoId + "---" + replaceMain + "/" + pipIndex + "/is in mTargeMaps:" + mTargetMaps.containsKey(tag) + "/is in mStartMaps:" + mStartMaps.containsKey(tag));

            if(replaceMain) {
                if(vId.equalsIgnoreCase(videoId))
                    targetIndex = i;
            } else {
                if(StringUtils.isNotBlank(vId) && vId.equalsIgnoreCase(videoId))
                    pipIndex = i;
            }

            if(mTargetMaps.containsKey(tag)) {
                animPics.add(mStartMaps.get(tag));
                targetPics.add(mTargetMaps.get(tag));
                mImgMaps.put(tag, mTargetMaps.get(tag).copy());
            } else {
                animPics.add(getCopyById(tag));
                targetPics.add(getCopyById(tag));
            }
        }

        if(replaceMain) {
            //物品热点跟随主视频
            if(mListener != null)
                mListener.mainVideoChanged(targetIndex);
            picView.swapDisplayState(targetIndex, 0, targetPip);

            if(mListener != null)
                mListener.updateTitle(((CameraCardView)picView.findViewWithTag(targetIndex+"")).getTitle());
        }

        printAnimState();

        return targetIndex;
    }

    private void printAnimState() {
        if(!Constant.DEBUG)
            return;
        Utils.Log("______________printAnimState START______________");
        for(ImageItem item : animPics)
            Utils.Log("start:" + item.width + "/" + item.x + "/" + item.y);
        Utils.Log("______________printAnimState DIVIDER______________");
        for(ImageItem item : targetPics)
            Utils.Log("end:" + item.width + "/" + item.x + "/" + item.y);
        Utils.Log("______________printAnimState END______________");
    }

    /**
     * 视图被拖动后,空位被剩余的视图补全
     */
    public void animUpSideViews(final boolean animate) {
        if(animate) {
            if (isAnimRunning())
                return;
            toggleAnimState(true);
        }
        List<String> views = picView.getRightSideViews();

        List<ImageItem> mOris = new ArrayList<>();
        List<ImageItem> mEnd = new ArrayList<>();

        Iterator<Map.Entry<String, ImageItem>> iter = sortSideVideos(views);

        //没有就不需要移动了
        if(iter == null) {
            if(animate)
                toggleAnimState(false);
            return;
        }

        int standY = getSideStartY(views.size());
        int index = 0;

        List<String> targetIds = new ArrayList<>();

        while (iter.hasNext()) {
            Map.Entry<String, ImageItem> entry = iter.next();

            int id = Integer.parseInt(entry.getKey());
            mOris.add(getCopyById(id));

            ImageItem item = new ImageItem(fixedSizeWSmall, fixedSizeHSmall, mStandardSideItem.x, standY + (fixedSizeHSmall+GAP)*index);

            mEnd.add(item);
            mImgMaps.put(id, item.copy());

            targetIds.add(entry.getKey());

            index++;
        }

        ObjectAnimator anim = ObjectAnimator.ofObject(this, "reFix", new AutoFitEvaluator(), new ImageList(mOris, targetIds), new ImageList(mEnd, targetIds));
        anim.setDuration(DURATION);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                if(animate)
                    toggleAnimState(false);
            }
        });
        anim.start();
    }

    public boolean isSoundSwitchEnabled() {
        return mEnableSoundSwitcher.get();
    }

    /**
     * 退出动画
     */
    private long mLastExecuteTime = 0;
    public void exit(IEnterAndExitListener listener) {
        mEnableSoundSwitcher.set(false);
        fullScreen = true;
        if (picView == null)
            return;
        
        //有时候状态不同步,而有新卡片等待入场的时候强制退出
        if(listener != null)
            mRemoved.set(false);
        if (mLastExecuteTime > 0 && System.currentTimeMillis() > mLastExecuteTime + 2000) {
            //等待时间超过2s,强制退出
            mRemoved.set(false);
        }
        if (mRemoved.get())
            return;
        mRemoved.set(true);
        mLastExecuteTime = System.currentTimeMillis();

        if(picView.getChildCount() <= 1)
            return;

        if(mListener != null)
            mListener.switchGoodsHotpotSize(true);

        //检查主镜头是否可见
        CameraCardView mainVideo = (CameraCardView) picView.findViewWithTag("0");
//        mainVideo.managePadding(false);
        mainVideo.resetSoundState();
        float videoX = mainVideo.getTranslationX();
        float videoY = mainVideo.getTranslationY();
        if(videoX < picView.getWidth()) {
            //如果非fullscreen模式且主镜头不可见,先让主镜头出来
            if(videoY + mainVideo.getHeight() > picView.getHeight()) {
                float upDistance = videoY + mainVideo.getHeight() - picView.getHeight();
                animRightView(false, upDistance, listener);
            } if (videoY < 0) {
                float downDistance = 0 - videoY;
                animRightView(true, downDistance, listener);
            } else {
                animToEixt(listener);
            }
        } else {
            animToEixt(listener);
        }
    }

    public void onDestroy() {
        if (picView == null)
            return;
    }

    /**
     * 当按左上角返回键时
     * @return
     */
    public boolean onBack() {
        if (fullScreen) {
            if(picView.getChildCount() > 1) {
                if(mListener != null && mListener.isInMultiVideoMode()) {
                    if(reverseFromFullScreen(false))
                        return true;
                }
            }
        }
        return false;
    }

    /**
     * 移动右侧的view
     * @param value
     */
    private void slideSideLayout(float value) {
        for(String id : picView.getRightSideViews()) {
            float targetY = getImageItem(Integer.parseInt(id)).y + value;
            picView.findViewWithTag(id).setTranslationY(targetY);
        }
    }

    /**
     * 移动右侧分镜头
     */
    private void animRightView(final boolean down, final float distance, final IEnterAndExitListener listener) {
        if(isAnimRunning())
            return;
        toggleAnimState(true);

        float start = down ? 0 : distance;
        float end = down ? distance : 0;
        ValueAnimator animator = ValueAnimator.ofFloat(start, end);
        animator.setDuration(DURATION);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                slideSideLayout(value);
            }
        });
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                for (String id : picView.getRightSideViews()) {
                    getImageItem(Integer.parseInt(id)).updateDelta(0, down ? distance : -distance);
                }

                toggleAnimState(false);
                animToEixt(listener);
            }
        });
        animator.start();
    }

    /**
     * 退出多镜头模式,不需要再保存具体的视频坐标
     */
    private void animToEixt(final IEnterAndExitListener listener) {
        if(isAnimRunning())
            return;
        toggleAnimState(true);

        animPics.clear();
        targetPics.clear();

        printEndRoute("卡片退场逻辑======start");

        int count = picView.getChildCount();

        for (int i = 0; i < count; i++) {
            int id = Integer.parseInt((String) picView.getChildAt(i).getTag());
            animPics.add(getCopyById(id));

            //主视频
            if (id == 0)
                targetPics.add(mFullSizePic.copy());
            else {
                ImageItem item = getCopyById(id);
                //大的不变
                if(item.width >= mMiddleSizePic.width) {
                    targetPics.add(getCopyById(id));
                } else {
                    if (item.x <= (mFullSizePic.width - item.width) / 2) {
                        ImageItem ii = new ImageItem(item.width, item.height, -item.width, item.y);
                        targetPics.add(ii);
                        mImgMaps.put(id, ii.copy());
                    } else {
                        ImageItem ii = new ImageItem(item.width, item.height, mFullSizePic.width, item.y);
                        targetPics.add(ii);
                        mImgMaps.put(id, ii.copy());
                    }
                }
            }
        }

        ObjectAnimator anim = ObjectAnimator.ofObject(this, "reLoc", new PointEvaluator(), new ImageItem(), new ImageItem());
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mRemoved.set(false);
                picView.clear();
                picView.onExit();

                //防止空指针
                try {
                    CameraCardView mainVideo = (CameraCardView) picView.findViewWithTag("0");
                    mainVideo.clear();
                    if(mListener != null) {
                        if(mainVideo.startPlayer())
                            mainVideo.seekTo((int) (getCurrentProgress() + 1000));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

                currentIndex = 0;
                toggleAnimState(false);

                if (listener != null)
                    listener.onExit();

            }
        });

        printEndRoute("卡片退场逻辑======end");

        anim.setDuration(DURATION);
        anim.start();
    }

    private ImageItem getCopyById(int id) {
        ImageItem item = mImgMaps.get(id);
        if(item == null) {
            Utils.Log(Utils.LogType.ERROR, TAG, "ImageItem:" + id + " in mImgMaps is null");
            return new ImageItem(mStandardHideItem.width, mStandardHideItem.height, mStandardHideItem.x, mStandardHideItem.y);
        }
        return item.copy();
    }

    public void toStandardPosition(final String tag, final ImageItem start, final ImageItem end, final IAnimEndListener mListener) {
        if(isAnimRunning())
            return;
        toggleAnimState(true);

        ObjectAnimator anim = ObjectAnimator.ofObject(this, "resetView", new TypeEvaluator<ImageItem>() {

            @Override
            public ImageItem evaluate(float fraction, ImageItem startValue, ImageItem endValue) {
                return new ImageItem(startValue.width + (endValue.width - startValue.width) * fraction,
                            startValue.height + (endValue.height - startValue.height) * fraction,
                            startValue.x + (endValue.x - startValue.x) * fraction,
                            startValue.y + (endValue.y - startValue.y) * fraction);
            }
        }, start, end);

        anim.setDuration(400);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                toggleAnimState(false);
                updateImageItemByIndex(tag, end.copy());

                if(mListener != null)
                    mListener.animEnd();
            }
        });
        anim.start();
    }

    /*****************************************属性动画回调*******************************************/
    public void setReLoc(ImageItem point) {
        picView.updatePics(exePics);
    }

    public void setReFix(ImageList state) {
        List<String> views = state.getIds() == null ? picView.getRightSideViews() : state.getIds();
        for (int i = 0; i < views.size(); i++) {
            View view = picView.findViewWithTag(views.get(i));
            view.setTranslationY(state.getImgs().get(i).y);
            view.setTranslationX(state.getImgs().get(i).x);
        }
    }

    public void setResizeAll(ImageList state) {
        List<String> views = state.getIds() == null ? picView.getRightSideViews() : state.getIds();
        for (int i = 0; i < views.size(); i++) {
            ImageItem item = state.getImgs().get(i);
            View view = picView.findViewWithTag(views.get(i));
            ViewGroup.LayoutParams param = view.getLayoutParams();
            param.width = item.width;
            param.height = item.height;
            view.setLayoutParams(param);
            view.setTranslationY(item.y);
            view.setTranslationX(item.x);
        }
    }

    public void setResetView(ImageItem item) {
        if(picView != null)
            picView.resizeView(item);
    }
    /*****************************************属性动画回调*******************************************/

    public void toggleAnimState(boolean on) {
        if(on)
            mHandler.sendEmptyMessageDelayed(RESET_ANIM_STATE, 2000);
        else
            mHandler.removeMessages(RESET_ANIM_STATE);
        mAnimRunning.set(on);

        Utils.Log(TAG, "toggleAnimState..." + on);
    }

    public boolean isAnimRunning() {
        //Utils.Log(TAG, "isAnimRunning..." + mAnimRunning.get());
        return mAnimRunning.get();
    }

    /**
     * 是否支持手势
     *
     * @return
     */
    public boolean canFling() {
//        if(picView == null || picView.getChildCount() == 1 || !fullScreen)
//            return false;
        if (picView == null || picView.getChildCount() == 1)
            return false;
        return true;
    }

    public boolean isFullScreen() {
        return fullScreen;
    }

    public int getDragDividerX() {
        if (mMiddleSizePic == null)
            return 0;

        if(fullScreen)
            return mFullSizePic.width;

        return mMiddleSizePic.x + mMiddleSizePic.width;
    }

    public int getPicInPicWidth() {
        if(fullScreen) {
            if (mPicInFullSize == null)
                return 0;
            return mPicInFullSize.width;
        } else {
            if (mPicInMiddleSize == null)
                return 0;
            return mPicInMiddleSize.width;
        }
    }

    public int getPicInPicHeight() {
        if(fullScreen) {
            if (mPicInFullSize == null)
                return 0;
            return mPicInFullSize.height;
        } else {
            if (mPicInMiddleSize == null)
                return 0;
            return mPicInMiddleSize.height;
        }
    }

    public int getPicInSideWidth() {
        if(mStandardSideItem == null)
            return 0;
        return mStandardSideItem.width;
    }

    public int getPicInSideHeight() {
        if(mStandardSideItem == null)
            return 0;
        return mStandardSideItem.height;
    }

    public int getLeft() {
        if(fullScreen)
            return 0;
        return mMiddleSizePic.x;
    }

    public int getTop() {
        if(fullScreen)
            return 0;
        return mMiddleSizePic.y;
    }

    public int getBottom() {
        if(fullScreen)
            return mFullSizePic.height;
        return mMiddleSizePic.y + mMiddleSizePic.height;
    }

    public int getStandardDistance() {
        if (mStandardSideItem == null || mPicInMiddleSize == null)
            return 0;
        return mStandardSideItem.x - mPicInMiddleSize.x - GAP;
    }

    public void resizeView(float ratio, View mCurrentView) {
        ViewGroup.LayoutParams param = mCurrentView.getLayoutParams();
        if(fullScreen) {
            param.width = (int) (mPicInFullSize.width + ratio * (mStandardSideItem.width - mPicInFullSize.width));
            param.height = (int) (mPicInFullSize.height + ratio * (mStandardSideItem.height - mPicInFullSize.height));
        } else {
            param.width = (int) (mPicInMiddleSize.width + ratio * (mStandardSideItem.width - mPicInMiddleSize.width));
            param.height = (int) (mPicInMiddleSize.height + ratio * (mStandardSideItem.height - mPicInMiddleSize.height));
        }
        mCurrentView.setLayoutParams(param);
    }

    /**
     * 打印路径
     */
    private static final String TAG = "ROUTE";
    public void printEndRoute(String tag) {
        Iterator<Map.Entry<Integer, ImageItem>> iterator = mImgMaps.entrySet().iterator();
        Utils.Log(TAG, "++++++++++++++++++++++++++++++" + tag);
        while (iterator.hasNext()) {
            Map.Entry<Integer, ImageItem> item = iterator.next();
            ImageItem value = item.getValue();
            Utils.Log(TAG, "id:" + item.getKey() + "_w:" + value.width + "_x:" + value.x + "_y:" + value.y);
        }
        Utils.Log(TAG, "++++++++++++++++++++++++++++++" + tag);
    }

    private Iterator<Map.Entry<String, ImageItem>> sortSideVideos(List<String> ids) {
        HashMap<String, ImageItem> oriMap = new HashMap<>();
        for (String id : ids) {
            oriMap.put(id, getImageItem(Integer.parseInt(id)));
        }
        if (oriMap != null && !oriMap.isEmpty()) {
            List<Map.Entry<String, ImageItem>> entryList = new ArrayList<>(oriMap.entrySet());
            Collections.sort(entryList,
                    new Comparator<Map.Entry<String, ImageItem>>() {
                        public int compare(Map.Entry<String, ImageItem> entry1,
                                           Map.Entry<String, ImageItem> entry2) {
                            int value1 = 0, value2 = 0;
                            try {
                                value1 = entry1.getValue().y;
                                value2 = entry2.getValue().y;
                            } catch (NumberFormatException e) {
                                value1 = 0;
                                value2 = 0;
                            }
                            return value1 - value2;
                        }
                    });
            Iterator<Map.Entry<String, ImageItem>> iter = entryList.iterator();
            return iter;
        }
        return null;
    }

    public void setIVideoStateListener(IVideoStateListener listener) {
        this.mListener = listener;
    }

    /***************************************属性动画轨迹计算器****************************************/
    public class PointEvaluator implements TypeEvaluator<ImageItem> {

        @Override
        public ImageItem evaluate(float fraction, ImageItem startValue, ImageItem endValue) {
            ImageItem pic;
            ImageItem end;
            ImageItem anim;
            try {
                for (int i = 0; i < animPics.size(); i++) {
                    pic = animPics.get(i);
                    end = targetPics.get(i);

                    anim = exePics.get(i);

                    anim.width = (int) (pic.width + fraction * (end.width - pic.width));
                    anim.height = (int) (pic.height + fraction * (end.height - pic.height));
                    anim.x = (int) (pic.x + fraction * (end.x - pic.x));
                    anim.y = (int) (pic.y + fraction * (end.y - pic.y));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return new ImageItem();
        }
    }

    public class AutoFitEvaluator implements TypeEvaluator<ImageList> {

        @Override
        public ImageList evaluate(float fraction, ImageList startValue, ImageList endValue) {
            List<ImageItem> results = new ArrayList<>();
            for (int i = 0; i < startValue.getImgs().size(); i++) {
                results.add(new ImageItem(startValue.getImgs().get(i).width + (endValue.getImgs().get(i).width - startValue.getImgs().get(i).width) * fraction,
                        startValue.getImgs().get(i).height + (endValue.getImgs().get(i).height - startValue.getImgs().get(i).height) * fraction,
                        startValue.getImgs().get(i).x + (endValue.getImgs().get(i).x - startValue.getImgs().get(i).x) * fraction,
                        startValue.getImgs().get(i).y + (endValue.getImgs().get(i).y - startValue.getImgs().get(i).y) * fraction));
            }
            return new ImageList(results, startValue.getIds());
        }
    }
    /***************************************属性动画轨迹计算器****************************************/

}